package jsu.yym.tiktok.server;


import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.qiniu.http.Client;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import jsu.yym.tiktok.mapper.Type;
import jsu.yym.tiktok.pojo.User;
import jsu.yym.tiktok.pojo.VariableNames;
import jsu.yym.tiktok.pojo.Video;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.qiniu.api.auth.digest.Mac;
import com.qiniu.api.config.Config;
import com.qiniu.api.rs.GetPolicy;
import com.qiniu.api.rs.URLUtils;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.processing.OperationManager;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.qiniu.util.UrlSafeBase64;
import org.springframework.web.multipart.MultipartFile;
//import com.wqdian.common.entity.media.QiNiuMedia;

/**
 * 七牛云存储的视频文件上传 和视频转码工具等
 *
 * @author "xinzhifu@knet.cn"
 */
@Service
public class QiniuMediaUtilService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private static final String domain= VariableNames.pubdomain;
    //设置好账号的ACCESS_KEY和SECRET_KEY
    private static final String ACCESS_KEY = VariableNames.accessKey; //这两个登录七牛
    private static final String SECRET_KEY = VariableNames.secretKey;
    //要上传的空间
    private static final String bucketName = VariableNames.bucket; //对应要上传到七牛上
    //密钥配置
    private static Auth auth =  Auth.create(ACCESS_KEY,SECRET_KEY);

    private static Configuration cfg  = new Configuration(Region.huanan());
    private static UploadManager uploadManager = new UploadManager(cfg);
    public static final String JPG = ".jpg";
    public static final String FLV = ".flv";
    public static final BucketManager bucketManager=new BucketManager(auth,cfg);
    private final Client client = new Client();


    /**
     * 获得下载地址
     * 这个获取的就是你上传文件资源的链接
     * @param filename
     * @return
     * @throws Exception
     */
    public String getFileResourceUrl(String filename) throws Exception {
        String downloadUrl = "";
        if (filename != null) {
            Mac mac = getMac();
            String baseUrl = URLUtils.makeBaseUrl(domain, filename);
            GetPolicy getPolicy = new GetPolicy();
            downloadUrl = getPolicy.makeRequest(baseUrl, mac);
        }
        String regex = "://(.+?)<Please apply your access key>:.+";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(downloadUrl);

        if (matcher.find()) {
            // 去掉多余部分
            String result = "://" + matcher.group(1);
            return result;
        } else {
            // 如果没有匹配，则返回原始 URL
            return downloadUrl;
        }
    }

    /**
     * 操作许可
     */
    private Mac getMac() {
        Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY);
        return mac;
    }

    /**
     * 七牛的视频截图
     */
    public String qiNiuMediaPrtScreen(String fileName) {
        String format = "jpg";
        String screenPic = ""; // 初始化为空字符串
        try {
            // 身份验证
            Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
            Zone z = Zone.zone0();
            Configuration c = new Configuration(z);
            // 新建一个OperationManager对象
            OperationManager operater = new OperationManager(auth, c);
            // 设置要截图的空间和key，并且这个key在你空间中存在(key就是文件的名字)
            String bucket = bucketName;
            String key = fileName;
            // 设置截图操作参数
            String fops = "vframe/" + format + "/offset/1/w/640/h/480/rotate/auto";
            // 设置截图的队列
            String pipeline = "video";
            // 可以对截图后的文件进行使用saveas参数自定义命名，当然也可以不指定文件会默认命名并保存在当前空间。
            String str = fileName.substring(0, fileName.indexOf("."));
            String urlbase64 = UrlSafeBase64.encodeToString(bucketName + ":" + str + "." + format);
            String pfops = fops + "|saveas/" + urlbase64;
            // 设置pipeline参数
            StringMap params = new StringMap().putWhen("force", 1, true).putNotEmpty("pipeline", pipeline);

            String persistid = operater.pfop(bucket, key, pfops, params);


            // 构建截图文件的URL地址
            screenPic = getFileResourceUrl(str + "." + format);

            // 检查并修正 URL 中的多余的 `http://` 前缀
            screenPic = screenPic.replaceFirst("^https?://", "https://");
            logger.info("视频截图成功. [persistid={}]", persistid);
        } catch (QiniuException e) {
            Response r = e.response;// 捕获异常信息
            logger.info(r.toString());// 请求失败时简单状态信息
            try {
                logger.info(r.bodyString());// 响应的文本信息
            } catch (QiniuException e1) {
                logger.error(e1.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("s"+screenPic);
        int startIndex = screenPic.indexOf("://");
        String url = null;
        if (startIndex != -1) {
            // 截取 startIndex 之后的部分
            url = screenPic.substring(startIndex + 3);
        }


       return url;
    }


    @Test
    public void test() throws Exception {
        String fileName = "1075_0b53fduaxsib4aaf4sgylvsdekaebo7qcoca.f0.mp4";

        String format = "mp4"; // 你可以指定截图的格式，如 jpg、png 等

        String screenPic = qiNiuMediaPrtScreen(fileName);

        System.out.println("URL: " + screenPic);
    }

    /**
     * 七牛的视频转码
     */
    public String qiNiuTransCodeWithWatermark(String fileName) {
        long startTime = System.currentTimeMillis();

        // 身份验证
        Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
        Zone z = Zone.zone0();
        Configuration c = new Configuration(z);
        OperationManager operator = new OperationManager(auth, c);

        String bucket = bucketName; // 原视频所在的存储空间
        String key = fileName; // 原视频文件名
        String targetFileName = key; // 目标文件名，保持与原文件名相同，这样会覆盖原视频
        String pipeline = "video"; // 设置转码的队列

        // 指定水印图片，此处假定水印图片已经上传到七牛云存储空间
        String watermarkImageURL = Type.url; // 替换为水印图片的URL
        String watermarkOptions = String.format("watermark/2/image/%s/dissolve/50/gravity/SouthEast", UrlSafeBase64.encodeToString(watermarkImageURL));

        // 设置转码操作参数，包括视频编码、分辨率、比特率以及添加水印
        String fops = String.format("avthumb/mp4/vcodec/libx264/acodec/aac/s/640x360/vb/1.25m|%s", watermarkOptions);

        // 设置保存位置
        String urlbase64 = UrlSafeBase64.encodeToString(bucket + ":" + targetFileName);
        String pfops = fops + "|saveas/" + urlbase64;

        // 设置pipeline参数
        StringMap params = new StringMap().putWhen("force", 1, true)
                .putNotEmpty("pipeline", pipeline);

        try {
            String persistid = operator.pfop(bucket, key, pfops, params);
            logger.info("视频转码成功.[persistid={}]", persistid);
        } catch (QiniuException e) {
            Response r = e.response;
            logger.info(r.toString());
            try {
                logger.info(r.bodyString());
            } catch (QiniuException e1) {
                logger.error("视频转码失败={}", e1.getMessage());
            }
        }

        long endTime = System.currentTimeMillis();
        logger.info("视频转码用时：" + (endTime - startTime) + "ms");

        return targetFileName;
    }


    // 采用默认策略，只需设置存储空间名
    public  String getUpToken(){
        return auth.uploadToken(bucketName);
    }
    //上传图片实现
    public User uploadFile(MultipartFile file){
        User user = new User();
        System.out.println("上传文件");
        try {
            byte[] uploadBytes = file.getBytes();//文件流转字节流
            //获取随机文件名
            String fileName = getRandomCharacterAndNumber(10)+".jpg";
            user.setFileName(fileName);
//            System.out.println(fileName);
            Response response = uploadManager.put(uploadBytes, fileName, getUpToken());
            //解析上传结果
            DefaultPutRet putPet = new Gson().fromJson(response.bodyString(),DefaultPutRet.class);
            //外部访问的资源地址
            String resUrl = VariableNames.pubdomain + putPet.key;
            user.setImage(resUrl);
            user.setFileName(fileName);
            return user;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    public Video uploadVideoFile(MultipartFile file){
        Video video = new Video();
        System.out.println("上传文件");
        try {
            byte[] uploadBytes = file.getBytes();//文件流转字节流
            //获取随机文件名
            String fileName = getRandomCharacterAndNumber(10)+".mp4";
            System.out.println(fileName);
            Response response = uploadManager.put(uploadBytes, fileName, getUpToken());
            logger.info("异常"+response.bodyString());
            //解析上传结果
            DefaultPutRet putPet = new Gson().fromJson(response.bodyString(),DefaultPutRet.class);
            //外部访问的资源地址
            String resUrl = VariableNames.pubdomain + putPet.key;
            video.setSrc(resUrl);
            video.setFileName(fileName);
            return video;
        } catch (IOException e) {
            logger.error("异常"+e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    private  String getRandomCharacterAndNumber(int length) {
        String val = "";
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; // 输出字母还是数字

            if ("char".equalsIgnoreCase(charOrNum)) // 字符串
            {
                int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; // 取得大写字母还是小写字母
                val += (char) (choice + random.nextInt(26));
                // int choice = 97; // 指定字符串为小写字母
                val += (char) (choice + random.nextInt(26));
            } else if ("num".equalsIgnoreCase(charOrNum)) // 数字
            {
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val;
    }

    /**
     * 删除文件
     */
    public boolean delete(String filename) throws QiniuException {
        if (filename.isEmpty()) {
            return false;
        }
        Response result = bucketManager.delete(bucketName, filename);
        if (result.statusCode==200)
            return true;
        return false;
    }

    @Test
    public void test2(){
        try {
            String s = ImageCensor("http://oayjpradp.bkt.clouddn.com/Audrey_Hepburn.jpg");
//            String s1 = resourcesCensor.ImageCensor();
//            System.out.println(resourcesCensor.getVideoCensorResultByJobID(s));
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(s);

            // 提取"suggestion"的值
            String suggestionValue = jsonNode.path("result").path("suggestion").asText();
            System.out.println(suggestionValue);
//            System.out.println(s1);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public String TextCensor(String text) throws QiniuException {
        // 构造post请求body
        Gson gson = new Gson();

        Map<String, Object> uri = new HashMap<>();
        uri.put("text", text);

        Map<String, Object> scenes = new HashMap<>();
        //pulp 黄  terror 恐  politician 敏感人物
        String[] types = {"antispam"};
        scenes.put("scenes", types);

        Map params = new HashMap();
        params.put("data", uri);
        params.put("params", scenes);

        String paraR = gson.toJson(params);
        byte[] bodyByte = paraR.getBytes();

        // 接口请求地址//http://ai.qiniuapi.com/v3/text/censor
        String url = "http://ai.qiniuapi.com/v3/text/censor";

        return post(url, bodyByte);
    }


    //参考api文档 https://developer.qiniu.com/dora/manual/4252/image-review
    //图片审核
    public String ImageCensor(String u) throws QiniuException {
        // 构造post请求body
        Gson gson = new Gson();

        Map<String, Object> uri = new HashMap<>();
        uri.put("uri", u);

        Map<String, Object> scenes = new HashMap<>();
        //pulp 黄  terror 恐  politician 敏感人物
        String[] types = {"pulp", "terror", "politician", "ads"};
        scenes.put("scenes", types);

        Map params = new HashMap();
        params.put("data", uri);
        params.put("params", scenes);

        String paraR = gson.toJson(params);

        //注意要指定编码格式 否则使用中文会报 badtoken错误
        byte[] bodyByte = paraR.getBytes(StandardCharsets.UTF_8);

        // 接口请求地址
        String url = "http://ai.qiniuapi.com/v3/image/censor";

        return post(url, bodyByte);
    }

    //参考api文档 https://developer.qiniu.com/dora/manual/4258/video-pulp
    //视频审核
    public String VideoCensor(String u) throws QiniuException {
        // 构造post请求body
        Gson gson = new Gson();

        Map bodyData = new HashMap();

        Map<String, Object> uri = new HashMap<>();
        uri.put("uri", u);

        Map<String, Object> params = new HashMap<>();

        Map<String, Object> scenes = new HashMap<>();
        //pulp 黄  terror 恐  politician 敏感人物
        String[] types = {"pulp", "terror", "politician"};

        Map<String, Object> cut_param = new HashMap<>();
        cut_param.put("interval_msecs", 500);

        params.put("scenes", types);
        params.put("cut_param", cut_param);

        bodyData.put("data", uri);
        bodyData.put("params", params);
        String paraR = gson.toJson(bodyData);
        byte[] bodyByte = paraR.getBytes(StandardCharsets.UTF_8);

        // 接口请求地址
        String url = "http://ai.qiniuapi.com/v3/video/censor";
        System.out.println(bodyByte);
        return post(url, bodyByte);
    }

    /**
     * 查询视频审核内容结果
     * 参考
     * https://developer.qiniu.com/censor/api/5620/video-censor#4
     * @param ID : 视频审核返回的 job ID
     *
     */
    public String getVideoCensorResultByJobID(String ID){
        String url = "http://ai.qiniuapi.com/v3/jobs/video/".concat(ID);
        System.out.println(url);
        String accessToken = (String) auth.authorizationV2(url).get("Authorization");
        StringMap headers = new StringMap();
        headers.put("Authorization", accessToken);

        try {
            com.qiniu.http.Response resp = client.get(url,headers);
            return resp.bodyString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String post(String url, byte[] body) throws QiniuException {
        com.qiniu.http.Response resp = client.post(url, body, auth.authorizationV2(url, "POST", body, "application/json"), Client.JsonMime);
        return resp.bodyString();
    }

}

